/***************************************************************************
 *   slist.h
 *
 *  Thu Nov 18 15:57:30 2010
 *  Copyright  2010  lius
 *  <lius@<host>>
 ****************************************************************************/
#ifndef __SLIST_H__
#define __SLIST_H__

typedef struct _slist_head slist_head;

struct _slist_head{
  slist_head * pre;
  slist_head * next;
};



static inline void INIT_SLIST_HEAD(slist_head *list)
{
	list->next = list;
	list->pre = list;
}

static inline void __slist_add(slist_head *newsh,
			      slist_head *pre,
			      slist_head *next)
{
	next->pre = newsh;
	newsh->next = next;
	newsh->pre = pre;
	pre->next = newsh;
}

static inline void slist_add(slist_head *newsh, slist_head *head)
{
	__slist_add(newsh, head, head->next);
}

static inline void slist_add_tail(slist_head *newsh, slist_head *head)
{
	__slist_add(newsh, head->pre, head);
}

static inline void __slist_del(slist_head * pre, slist_head * next)
{
	next->pre = pre;
	pre->next = next;
}

static inline void slist_del(slist_head *entry)
{
	__slist_del(entry->pre, entry->next);
	entry->next = NULL;
	entry->pre = NULL;
}

static inline void slist_replace(slist_head *old,
				slist_head *newsh)
{
	newsh->next = old->next;
	newsh->next->pre = newsh;
	newsh->pre = old->pre;
	newsh->pre->next = newsh;
}

static inline void slist_replace_init(slist_head *old,
					slist_head *newsh)
{
	slist_replace(old, newsh);
	INIT_SLIST_HEAD(old);
}

static inline void list_del_init(slist_head *entry)
{
	__slist_del(entry->pre, entry->next);
	INIT_SLIST_HEAD(entry);
}

static inline void list_move(slist_head *list, slist_head *head)
{
	__slist_del(list->pre, list->next);
	slist_add(list, head);
}

static inline void list_move_tail(slist_head *list,
				  slist_head *head)
{
	__slist_del(list->pre, list->next);
	slist_add_tail(list, head);
}

static inline int list_is_last(const slist_head *list,
				const slist_head *head)
{
	return list->next == head;
}

static inline int list_empty(const slist_head *head)
{
	return head->next == head;
}

static inline int list_empty_careful(const slist_head *head)
{
	slist_head *next = head->next;
	return (next == head) && (next == head->pre);
}

#ifndef offsetof
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif

#define container_of(ptr, type, member) ({                      \
        const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
        (type *)( (char *)__mptr - offsetof(type,member) );})

#define slist_entry(ptr, type, member) \
	container_of(ptr, type, member)

#define slist_for_each(pos, head) \
	for (pos = (head)->next; pos != (head); pos = pos->next)

#endif
